package ro.flashbite.sound
{
	import flash.display.MovieClip;
	
	import ro.flashbite.interfaces.IDestroyable;
	import ro.flashbite.loggers.ILogger;
	import ro.flashbite.loggers.LoggerFactory;
	import ro.flashbite.utils.framer.FrameBeacon;
	import ro.flashbite.utils.framer.ITickUpdater;
	
	/**
	 * This class is responsable for handling the voices of Characters, one at a time ;)
	 * @author Adrian Barbu
	 */
	internal final class SpeechManager implements IDestroyable
	{
		private static const MOUTH_FRAMES_SYNC	:	uint = 1;
		private static const AMPLITUDE_BOOST	:	Number = 1;
		
		private var _mcMouth			:	MovieClip;
		private var _mouthID			:	String;
		
		private var _mcMouthTotalFrames	:	uint;
		private var _counterSync		:	int;
		
		private var _framer				:	ITickUpdater;
		
		private var _syncSound			:	Sound2;
		
		private var _logger				:	ILogger;
		
		// ================================================================================================================================
		// CONSTRUCTOR
		// ================================================================================================================================
		
		public function SpeechManager() 
		{
			_constructor();
		}
		private function _constructor():void
		{
			_framer = FrameBeacon.getInstance();
			
			_logger = LoggerFactory.getLogger("SpeechManager - " + " no mouthID");
		}
		
		// ================================================================================================================================
		// PUBLIC 
		// ================================================================================================================================
		
		public function setMouth(mcMouth:MovieClip, mouthID:String):void
		{
			_mcMouth = mcMouth;
			_mouthID = mouthID;
			if (_mcMouth) _mcMouthTotalFrames = _mcMouth.totalFrames;
			
			_logger = LoggerFactory.getLogger("SpeechManager - " + _mouthID);
		}
		
		public function startSync(sound:Sound2):void
		{
			stopSync();
			_syncSound = sound;
			
			_framer.registerCallback(onMouthEnterFrame);
			
			/*if (_logger)
				_logger.debug("Start sync");*/
		}
		
		public function stopSync():void
		{
			if (_mcMouth) {
				_mcMouth.gotoAndStop(1);
			}
			_framer.unregisterCallback(onMouthEnterFrame);
			
			_counterSync = 0;
			
			/*if (_logger)
				_logger.debug("Stop sync");*/
		}
		
		// ================================================================================================================================
		// PRIVATE
		// ================================================================================================================================
		
		private function onMouthEnterFrame(e:* = null):void 
		{
			if (_syncSound && _mcMouth) {
				if (++_counterSync % MOUTH_FRAMES_SYNC == 0) {
					var amplitude:Number;
					if (SoundManager.GlobalVolume != 0) {
						amplitude = _syncSound.getAmplitude() * AMPLITUDE_BOOST / SoundManager.GlobalVolume / _syncSound.peak;
					} else amplitude = 0;
					//_logger.debug("Registered mcMouth percentage amplitude : " + amplitude);
					var targetFrameToGo:int = Math.min(_mcMouthTotalFrames, Math.max(1, amplitude * _mcMouthTotalFrames));
					_mcMouth.gotoAndStop(targetFrameToGo);
					//if (_logger)
						//_logger.debug("Registered mcMouth goes to frame : " + targetFrameToGo);
				}
			}
		}
		
		// ================================================================================================================================
		// DESTRUCTOR
		// ================================================================================================================================
		
		public function destroy():void 
		{
			stopSync();
			
			_mcMouth = null;
			_mouthID = null;
			
			if (_framer) {
				_framer.unregisterCallback(onMouthEnterFrame);
				_framer = null;
			}
			
			_logger = null;
		}

		// ================================================================================================================================
		// GETTERS
		// ================================================================================================================================
		
		public function get mouthID():String { return _mouthID;	}
	}
}